<?php

namespace control;

//管理员后台-审核相关类

class auditClass extends adIndexClass
{

    /**
     * 写入操作记录（单据使用）
     *
     * @param $id
     * @param $type
     * @param $operate
     * @return string
     */
    public static function operateRecord($id, $type, $operate): string
    {
        $staff = query('staff', "stid = '" . self::$stid . "'");
        $job   = query('job', "id = '$staff[jobId]'");
        return auditingFollow(array(
            "type"      => $type,
            "typeId"    => $id,
            "text"      => "【{$staff['name']}】" . $operate,
            'job'       => self::findStaffDepartment(self::$stid) . '-' . $job['name'],
            'staffName' => $staff['name'],
        ));
    }

    /**
     * 执行函数
     *
     * @param string $cla
     * @param string $fun
     * @param array $data
     * @return bool|mixed
     */
    public static function call(string $cla, string $fun, array $data = [])
    {
        if (!empty($cla) && !empty($fun)) {
            $cla      = (stripos($cla, 'class') !== false) ? $cla : $cla . 'Class';
            $objClass = new (__NAMESPACE__ . '\\' . $cla)();
            if (method_exists($objClass, $fun)) {
                if (!empty($data) && is_array($data)) {
                    return $objClass->$fun($data);
                } else {
                    return $objClass->$fun();
                }
            } else {
                test($cla . '函数' . $fun . '不存在');
                return true;
            }
        }
        return false;
    }


    /**
     * 本次操作是否有权限，包括审核、撤销
     *
     * @param string $table
     * @param string $targetId
     * @param string $type
     * @param null $flowName
     * @return bool
     */
    public static function auditFlag(string $table, string $targetId, string $type = 'approver', $flowName = null): bool
    {
        $bool = false;
        $data = query($table, " id = '$targetId' ");
        if ($data) {
            $field = array_key_exists('auditing', $data) ? 'auditing' : 'examine';
            //审核流程
            $auditing = (array)json_decode($data[$field], true);
            switch ($type) {
                // 撤销审批 当前人在审批人中
                case 'cancel':
                    $approver  = [];
                    $is_single = false;
                    foreach ($auditing as $val) {
                        if ($val['form'] == 'approver') {
                            if (self::is_single_array($val['stateNode'])) {
                                $is_single = true;
                                $approver  = array_merge($val['stateNode'], $approver);
                            } else {
                                $approver = array_merge(self::returnStidCollection($val['stateNode']), $approver);
                            }
                        }
                    }
                    //加上创建人
                    $own = !empty($data['stid']??'') ? [$data['stid']] : [];
                    //加上提交人
                    $audit = query('audit', " targetId = '".($data['id']??'')."' ", "applicantId");
                    if($audit['applicantId']) $own[] = $audit['applicantId'];
                    $bool = $is_single ? in_array(self::$stid, array_merge(array_keys($approver),$own)) : in_array(self::$stid, array_merge($approver,$own));
                    break;
                // 审核
                case 'approver':
                    $where = self::flowWhere($flowName, $data['orderNo'] ?? '');
                    $audit = query('audit', "targetId = '$targetId' $where order by updateTime desc");
                    $bool  = in_array(self::$stid, array_filter(explode(',', $audit['approverId'])));
                    break;
                case 'selfChoose':
                    //判断是否存在审批人自选
                    $bool = false;
                    foreach ($auditing as $val) {
                        if ($val['form'] == 'approver' && $val['state'] == '审核中' && $val['type'] == '审批人自选') {
                            $bool = true;
                        } elseif ($val['form'] == 'approver' && $val['state'] == '审核中') {
                            break;
                        }
                    }
                    break;
            }
        }
        return $bool;
    }

    /**
     * 是否为一位数组
     */
    public static function is_single_array($array): bool
    {
        if (count($array) == count($array, 1) && count($array) > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 验证参数
     *
     * @param string $body
     * @param string $type
     * @return string|array
     */
    public static function validateBody(string $body, string $type = ''): array|string
    {
        $warn = '';
        if (static::isNull($body)) {
            $warn = L('audit.table.bodyEmpty');
        } else {
            $body = json_decode(self::encryptDecrypt($body, true), true);
            if (!is_array($body)) {
                $warn = L('audit.table.bodyPara');
            } else {
                $field      = ['table' => $body['table']];
                $annotation = ['table' => L('audit.table.dzdx')];
                $rules      = ['table' => 'required'];
                switch ($type) {
                    // 撤销审批
                    case 'cancel':
                        // 审批
                    case 'approval':
                        $field      = array_merge($field, [
                            'state'   => $body['state'],
                            'field'   => $body['field'],
                            'value'   => $body['value'],
                            'process' => $body['process'],
                        ]);
                        $annotation = array_merge($annotation, [
                            'state'   => L('audit.table.dqzt'),
                            'field'   => L('audit.table.dzzd'),
                            'value'   => L('audit.table.diao_zheng_zhi'),
                            'process' => L('audit.table.chu_li_lei_xing'),
                        ]);
                        $rules      = array_merge($rules, [
                            'state' => 'required',
                            'field' => 'required',
                            'value' => 'required',
                        ]);
                        break;
                }
                // 校验是否符合规则
                $vt     = new \verify();
                $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
                if ($result === false) {
                    $warn = $vt->getErrs()[0];  // 多个规则提示最前面一条
                }
            }
        }
        return static::isNull($warn) ? $body : $warn;
    }

    /**
     * 构造更新参数
     *
     * @param array $field
     * @param array $data
     * @param bool $accept
     * @return array
     */
    private static function getUpdateValue(array $field, array $data, bool $accept = true): array
    {
        $params = [];
        foreach ($field as $value) {
            if ($accept === true) {
                $params[$value] = $data[$value][0] ?? '';
            } else {
                $params[$value] = $data[$value][1] ?? '';
            }
        }
        return $params;
    }

    /**
     * 获取 部门id
     *
     * @param string $id
     * @return string
     */
    public static function getDepartmentId(string $id): string
    {
        $temp = '';
        $info = query('department', " id = '$id' ");
        if ($info['id']) {
            $temp .= $info['id'] . ';';
            if (!empty($info['pid'])) {
                $temp .= self::getDepartmentId($info['pid']);
            }
        }
        return $temp;
    }

    /**
     * 员工所在部门、职位、个人id的集合
     *
     * @param string $stid
     * @return array
     */
    public static function whereDoI(string $stid): array
    {
        $data = [$stid];
        // 获取职位所在
        $jobId  = self::findStaff($stid, 'jobId');
        $data[] = $jobId;
        // 初始部门id
        $departmentId = self::findStaffDepartment($stid, 'id');
        // 获取部门所在集合
        $string = self::getDepartmentId($departmentId);
        $array  = explode(';', $string);
        $result = self::filterArray($array);
        return self::filterArray(array_merge($data, $result));
    }

    /**
     * 比较结果
     *
     * @param string $data
     * @param string $data2
     * @param string $operator
     * @return bool
     */
    public static function getOperator(string $data, string $data2, string $operator): bool
    {
        $bool = false;
        switch ($operator) {
            case '大于':
                $bool = ($data > $data2);
                break;
            case '大于等于':
                $bool = ($data >= $data2);
                break;
            case '等于':
                $bool = ($data == $data2);
                break;
            case '小于':
                $bool = ($data < $data2);
                break;
            case '小于等于':
                $bool = ($data <= $data2);
                break;
            case '介于':
                // 左开右闭 (]
                if (is_numeric($data)) {
                    $array = explode(',', $data2);
                    $bool  = ($array[0] < $data && $data <= $array[1]);
                }
                break;
        }
        return $bool;
    }


    /**
     * 获取条件
     *
     * @param array $examine
     * @param array $info
     * @return string|array
     */
    public static function getCondition(array $examine, array $info): array|string
    {
        $conditions = $original = (array)json_decode($examine['conditions'], true);
        if (empty($conditions)) {
            return L('audit.table.splctjwk');
        }
        // 所在范围
        $range = self::whereDoI(self::$stid);
        foreach ($conditions as $key => $condition) {
            // 确定适用范围
            $examineRange = explode(';', $condition['staff[]']);
            $array        = array_filter($examineRange);
            // 交集
            $result = array_intersect($range, $array);
            if (empty($result)) {
                unset($conditions[$key]);
            }
        }

        // 条件
        require_once "examineData.php";
        $array = isset($examineData[$examine['type']][$examine['target']]) ? array_keys($examineData[$examine['type']][$examine['target']]) : [];
        if ($array) {
            // 条件存在
//            $field = $array[0];
            foreach ($conditions as $key => $condition) {
                if (static::isNull($condition['field'])) {
                    continue;
                }
                $bool = self::getOperator($info[$condition['field']], $condition['value'], $condition['range']);
                if ($bool !== true) {
                    unset($conditions[$key]);
                }
            }
        }
        // 为空
        if (empty($conditions)) {
            $condition = [];
            foreach ($original as $value) {
                if ($value['name'] == '默认条件') {
                    $condition = $value;
                }
            }
            if (empty($condition)) {
                return L('audit.table.gsplczwmrtj');
            } else {
                return $condition;
            }
        } else {
            // 选择优先级高的条件
            $last_names = array_column($conditions, 'level');
            array_multisort($last_names, SORT_DESC, $conditions);
            return $conditions[0];
        }
    }


    /**
     * 发起审批
     *
     * @param $id
     * @param $body
     * @param $node
     * @return bool|int|string
     */
    private static function start($id, $body, $node): bool|int|string
    {
        // 执行发起操作
        $warn = self::launch($id, $body, $node);
        if ($warn === true) {
            // 完成发起后执行函数
            $process = $body['process']['after'];
            if (is_array($process) && !empty($process)) {
                $process['data'] = $process['data'] ?? [];
                self::call($process['cla'], $process['fun'], $process['data']);
            }
            $_SESSION['warn'] = L('audit.table.czcg');
            $warn             = 2;
        }
        return $warn;
    }

    /**
     * 寻找审批流程
     *
     * @param $id
     * @param $body
     * @return array|string|null
     */
    public static function findFlow($id, $body): array|string|null
    {
        $info = query($body['table'], " id = '$id' ");
        if (empty($info['id'])) {
            return L('audit.table.jlbcz');
        } else {
            //当前处于审批人自选阶段时
            if ($info['state'] == '审核中' && self::judgeSelfChoose(json_decode($info['examine'], true))) {
                $auditNode = json_decode($info['examine'], true);
            } else {
                // 判断审批流程是否存在
                $examine = query('examine', " target = '{$body['name']}' ");
                if (empty($examine)) {
                    return str_replace(['{{name}}'], [$body['name']], L('audit.table.flow_find'));
                }

                if ($examine['state'] == '停用') {
                    return str_replace(['{{name}}'], [$body['name']], L('audit.table.stopFlow'));
                }
                // 所在范围
                $range        = self::whereDoI(self::$stid);
                $array        = (array)json_decode($examine['staff'], true);
                $examineRange = self::filterArray(explode(';', $array['id'] ?? ''));
                if (!array_intersect($range, $examineRange)) {
                    return str_replace(['{{name}}'], [$body['name']], L('audit.table.findNoFlow'));
                }
                // 判断条件是否符合
                $condition = self::getCondition($examine, $info);
                if (!is_array($condition)) {
                    return $condition;
                }

                $cid  = $condition['id'];
                $node = json_decode($examine['node'], true);
                // 根据类型选择更新审批节点，更新对应记录状态 审批人自选时，不发送待办
                $auditNode = [];
                // 上级
                $superiorArray = explode(';', self::getSuperior(self::$stid));
                foreach ($node[$cid] as $value) {
                    $arr = [];
                    switch ($value['type']) {
                        case '指定成员':
                            $arr = explode(';', $value['staff[]']);
                            break;
                        case '指定上级':
                        case '连续多级上级':
                            $arr = self::getSuperiorAppoint($value['type'], $value['value'], $superiorArray);
                            break;
                        case '指定职位':
                            $arr = self::getStaffIdByJob($value['staff[]']);
                            break;
                        case '部门负责人':
                            $arr = self::getDepartmentManager($id, $body, $value);
                            break;
                        case '审批人自选':
                            // 非本次处理流程
                            break;
                    }
                    if (!is_array($arr)) {
                        return $arr;
                    }
                    $arr                = self::filterArray($arr);
                    $stateNode          = [];
                    $flag               = ($value['form'] == 'approver') ? '审核中' : '待抄送';
                    $value['staff[]']   = '';
                    $value['staffName'] = '';
                    if (!empty($arr)) {
                        foreach ($arr as $v) {
                            if (!static::isNull($v)) {
                                $stateNode[]        = [
                                    'stid'  => $v,
                                    'state' => $flag,
                                ];
                                $value['staff[]']   .= $v . ';';
                                $value['staffName'] .= self::findStaff($v) . ';';
                            }
                        }
                    }
                    $value['state']     = $flag;
                    $value['stateNode'] = $stateNode;
                    $auditNode[]        = $value;
                }
            }
            return $auditNode;
        }
    }

    /**
     * 获取部门负责人
     */
    public static function getDepartmentManager($id, $body, $data): array|string
    {
        $staffs = [];
        if ($data['value'] == '发起人部门负责人') {
            $job        = query('job', "id = '" . self::$staff['jobId'] . "'");
            $department = query('department', "id = '$job[departmentId]'");
            if (!empty($department['manager'])) {
                $staffs[] = $department['manager'];
            } else {
                return L('audit.table.wzdfqrdbmfzr');
            }
        } elseif ($data['value'] == '成员部门负责人') {
            $info = query($body['table'], " id = '$id' ");
            switch ($body['name'] == L('audit.table.rzsq')) {
                case L('audit.table.rzsq'):
                    $job        = query('job', "id = '$info[jobId]'");
                    $department = query('department', "id = '$job[departmentId]'");
                    if (!empty($department['manager'])) {
                        $staffs[] = $department['manager'];
                    } else {
                        return L('audit.table.wzdcygdbmfzr');
                    }
                    break;
                default:
                    $info['staffId'] = $info['staffId'] ?? $info['stid'];
                    $staff           = query('staff', "stid = '$info[staffId]'");
                    $job             = query('job', "id = '$staff[jobId]'");
                    $department      = query('department', "id = '$job[departmentId]'");
                    if (!empty($department['manager'])) {
                        $staffs[] = $department['manager'];
                    } else {
                        return L('audit.table.wzdcygdbmfzr');
                    }
                    break;
            }
        }
        return $staffs;
    }

    /**
     * 获取状态一维数组
     */
    public static function returnStateCollection($array): array
    {
        return array_column(array_filter($array, function ($val) {
            return $val;
        }), 'state');
    }

    /**
     * 获取员工ID一维数组
     */
    public static function returnStidCollection($array): array
    {
        return array_column(array_filter($array, function ($val) {
            return $val;
        }), 'stid');
    }

    /**
     * 根据职位寻找审批人
     */
    public static function getStaffIdByJob($jobList): array
    {
        $data  = [];
        $array = array_filter((array)explode(';', $jobList));
        foreach ($array as $jobId) {
            $result = find(array('table' => 'staff', 'where' => "state in ('转正','试用','留职') and jobId = '$jobId' and workFlow = '已复核' order by time asc"));
            foreach ($result['array'] as $staff) {
                $data[] = $staff['stid'];
            }
        }
        return $data;
    }

    /**
     * 判断审批流程中是否有审批人自选
     *
     * @param $flow
     * @return bool
     */
    public static function judgeSelfChoose($flow): bool
    {
        $bool = false;
        foreach ($flow as $array) {
            if ($array['type'] == '审批人自选' && $array['form'] == 'approver' && $array['state'] == '审核中') {
                $bool = true;
                break;
            } elseif ($array['form'] == 'approver' && $array['state'] == '审核中') {
                break;
            }
        }
        return $bool;
    }

    /**
     * 执行审批
     *
     * @param string $id 时间id
     * @param array $body body
     * @param array $array 审批流程
     */
    public static function launch(string $id, array $body, array $array): bool|string
    {
        // 执行发起时验证函数
        $process = $body['process']['before'];
        if (is_array($process) && !empty($process) && !empty($process['fun'])) {
            $warn = self::call($process['cla'], $process['fun'], $process['data']);
            if ($warn !== true) {
                return $warn;
            }
        }
        $flag = false;//判断是否有审批节点
        $auto = false;
        foreach ($array as $item) {
            if ($item['form'] == 'approver') {
                $flag = true;
                if (isset($item['isAuto']) && $item['isAuto'] == '否') {
                    $auto = true;
                }
            }
        }
        if (!$flag) {
            return L('audit.table.csplczmzspjd');
        }
        if (!$auto) {
            return L('audit.table.zbnszqzdsplcxyqzygjdwfzdspzt');
        }
        $query = query($body['table'], " id = '$id' ");
        // 查找审批人
        $approver = self::findAuditPeople($array);
        $field    = [
            'examine' => json_encode($approver['flow'], 320),
            'state'   => isset($body['process']['state']) && $body['process']['state'] ? $body['process']['state'] : '审核中',
        ];
        $warn     = static::update([
            'table' => $body['table'],
            'field' => $field,
            'where' => " id = '$id' ",
        ]);
        if ($warn != '更新成功') {
            return $warn;
        } else {
            $applicantDepartment = self::findStaffDepartment(self::$stid);
            $staffId             = self::$stid;
            $field               = [
                'orderNo'  => query($body['table'], " id = '$id' ")['orderNo'] ?? '',
                'flowName' => $body['name'],
                'targetId' => $id,
            ];
            $audit               = query('audit', generateWhere($field));
            $field               = array_merge($field, [
                'targetCla' => $body['process']['detail']['cla'],
                'targetFun' => $body['process']['detail']['fun'],
            ]);
            if (empty($audit['id'])) {
                // 写入审批表
                $auditId = self::getNo();
                static::insert([
                    'table' => 'audit',
                    'field' => array_merge($field, [
                        'id'                  => $auditId,
                        'applicant'           => self::findStaff(self::$stid),
                        'applicantId'         => self::$stid,
                        'applicantDepartment' => $applicantDepartment,
                        'commitTime'          => date('Y-m-d H:i:s'),
                        'workFlow'            => '审核中',
                        'approver'            => implode(',', $approver['staffName']),
                        'approverId'          => implode(',', $approver['staffId']),
                        'time'                => date('Y-m-d H:i:s'),
                    ]),
                ]);
            } else {
                $auditId = $audit['id'];
                // 判断审批流程 空是提交审批，不为空则是审批人自选
                if (empty($query['examine'])) {
                    $applicant = [
                        'applicant'           => self::findStaff(self::$stid),
                        'applicantId'         => self::$stid,
                        'applicantDepartment' => $applicantDepartment,
                        'commitTime'          => date('Y-m-d H:i:s'),
                    ];
                } else {
                    $applicant           = [];
                    $applicantDepartment = self::findStaffDepartment($audit['applicantId']);
                    $staffId             = $audit['applicantId'];
                    if ($query['state'] == '草稿') {
                        $staffId   = self::$stid;
                        $applicant = [
                            'applicant'           => self::findStaff(self::$stid),
                            'applicantId'         => self::$stid,
                            'applicantDepartment' => $applicantDepartment,
                            'commitTime'          => date('Y-m-d H:i:s'),
                        ];
                    }
                }
                static::update([
                    'table' => 'audit',
                    'field' => array_merge($applicant, [
                        'workFlow'   => '审核中',
                        'approver'   => implode(',', $approver['staffName']),
                        'approverId' => implode(',', $approver['staffId']),
                    ]),
                    'where' => " id = '$audit[id]'",
                ]);
            }
            // 审批人自选时，不发送待办
            $text = str_replace(['{{deptName}}', '{{staffName}}', '{{name}}'], [$applicantDepartment, self::findStaff($staffId), $body['name']], L('audit.table.commitAudit'));
            self::sendTip($approver['staffId'], $auditId, $text);

            self::findAutoNode($approver['flow'], $audit['flowName'], $audit['id'], "【{$applicantDepartment}】-【" . self::findStaff($staffId) . "】提交的【{$body['name']}】需要您审批");

            // 执行抄送
            $copyStaff = self::findCopy($approver['flow'], $id, $body['table']);
            self::batchMessage($copyStaff, $auditId, str_replace(['{{deptName}}', '{{staffName}}', '{{name}}'], [$applicantDepartment, self::findStaff($staffId), $body['name']], L('audit.table.copySee')));
            return true;
        }
    }


    /**
     * 获取我的上级
     *
     * @param $stid
     * @return string
     */
    public static function getSuperior($stid): string
    {
        $temp = '';
        $info = query('staff', " stid = '$stid' and state not in ('离职','留职') ");
        if ($info['manager']) {
            $manager = query('staff', "stid = '$info[manager]' and state not in ('离职','留职')");
            $temp    .= $manager['stid'] . ';';
            $temp    .= self::getSuperior($info['manager']);
        }
        return $temp;
    }

    /**
     * 获取指定上级数据
     *
     * @param string $type 类型
     * @param string $key 层级
     * @param array $arr 数据
     * @return
     */
    public static function getSuperiorAppoint(string $type, string $key, array $arr): array|string
    {
        if ($type == '指定上级') {
            $search  = ['直接上级', '第二级上级', '第三级上级', '第四级上级', '第五级上级', '第六级上级', '第七级上级', '第八级上级', '第九级上级', '第十级上级',];
            $replace = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
            $key     = str_replace($search, $replace, $key) - 1;
            return isset($arr[$key]) ? [$arr[$key]] : L('audit.table.wzdsj');
        } else {
            $search  = ['最高上级', '第二级上级', '第三级上级', '第四级上级', '第五级上级', '第六级上级', '第七级上级', '第八级上级', '第九级上级', '第十级上级',];
            $replace = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
            $key     = str_replace($search, $replace, $key);
            return $key == 0 ? array_slice($arr, $key) : array_slice($arr, 0, $key + 1);
        }
    }

    /**
     * 撤销审批
     *
     * @param $id
     * @param $body
     * @return string|bool
     */
    public static function cancel($id, $body): bool|string
    {
        $info = query($body['table'], " id = '$id' ");
        if (empty($info['id'])) {
            $warn = L('audit.table.jlbcz');
        } else {
            $where = self::flowWhere($body['name'] ?? '', $info['orderNo'] ?? '');

            $audit = query('audit', "targetId = '$id' $where order by updateTime desc");
            $field = [];
            $keys  = array_keys($info);
            // 提交时间 审核时间
            $fields = ['commitTime', 'passTime'];
            foreach ($fields as $key) {
                if (in_array($key, $keys)) {
                    $field[$key] = '';
                }
            }
            $field['examine'] = '';
            // 取消状态
            $warn = static::update([
                'table' => $body['table'],
                'field' => array_merge($field, self::getUpdateValue($body['field'], $body['value'])),
                'where' => " id = '$id' ",
            ]);
            if ($warn != '更新成功') {
                $warn = L('audit.table.cxspsb');
            } else {
                $warn  = L('audit.table.cxspcg');
                $staff = query('staff', "stid = '" . self::$stid . "'");
                $job   = query('job', "id = '" . $staff['jobId'] . "'");
                //添加审批记录
                auditingFollow([
                    "type"      => $audit['flowName'],
                    "typeId"    => $audit['id'],
                    "text"      => "【" . self::$staff['name'] . "】撤销了【{$audit['flowName']}】",
                    'staffName' => self::$staff['name'],
                    'job'       => self::findStaffDepartment(self::$stid) . '-' . $job['name'],
                ]);
                insert([
                    "table" => "log", "field" => [
                        'type' => 'my',
                        'coid' => self::$coid,
                        'stid' => self::$stid,
                        'text' => str_replace(['{{staffName}}', '{{flowName}}', '{{id}}'], [self::$staff['name'], $audit['flowName'], $audit['targetId']], L('audit.table.cancelAudit')),
                    ],
                ]);
                //撤销企业微信消息
                self::revokeMessage($audit['id']);
                // 删除待办
                delete([
                    'table' => 'backlog',
                    'where' => generateWhere([
                        'typeId'   => $audit['id'],
                        'workFlow' => '待处理',
                    ]),
                ]);
                // 删除消息
                delete([
                    'table' => 'message',
                    'where' => generateWhere([
                        'typeId' => $audit['id'],
                        'see'    => '否',
                    ]),
                ]);

                // 执行取消后的函数
                $process = $body['process']['after'];
                if (is_array($process) && !empty($process)) {
                    self::call($process['cla'], $process['fun'], $process['data'] ?? []);
                }
            }
        }
        return $warn;
    }

    /**
     * 催办
     *
     * @param string $id
     * @return string
     */
    public function press(string $id): string
    {
        $audit = query('audit', " id = '$id' ");
        if (!$audit) {
            return L('audit.table.spjlbcz');
        } else {
            $approver = explode(',', $audit['approverId']);
            // 审批人列表
            $approverArr = self::filterArray($approver);
            foreach ($approverArr as $stid) {
                static::update([
                    'table' => 'backlog',
                    'field' => [
                        'urging' => '是',
                        'time'   => $this->time,
                    ],
                    'where' => " stid = '$stid'  AND typeId = '$id' AND workFlow = '待处理' ;",
                ]);
            }
            return L('audit.table.cbcg');
        }
    }

    /**
     * Desc : 单独提交审核
     * User : you name
     * Date : 2023-11-16 15:42
     * @param $id 审批记录id
     * @param $body 审批参数
     * @return array|bool|int|string|null
     */
    public static function submitApprovalSignle($id,$body)
    {
        $instance = new self();
        $bodyArray = self::validateBody($body);
        $flow = (!is_array($bodyArray)) ? $bodyArray : self::findFlow($id, $bodyArray);
        $data = '';
        if (!is_array($flow)) {
            $warn = $flow;
        } else {
            //先判断流程中是否有审批人自选，有则选人
            $result = self::judgeSelfChoose($flow);
            if ($result === true) {
                $warn = 1;
                $data = $instance->addAuditPeople($id, $body, $flow);
            } else {
                $warn = self::start($id, $bodyArray, $flow);
            }
        }
        return ['warn'=>$warn,'data'=>$data];
    }

    // 操作中转
    public function operate()
    {
        $act  = $this->post('act');
        $id   = $this->post('id');
        $body = $this->post('body');
        switch ($act) {
            // 撤销审批
            case 'cancel':
                $body = self::validateBody($body, 'cancel');
                $warn = (!is_array($body)) ? $body : self::cancel($id, $body);
                break;
            // 发起审批
            case 'start':
                $body = self::validateBody($body);
                $flow = (!is_array($body)) ? $body : self::findFlow($id, $body);
                if (!is_array($flow)) {
                    $warn = $flow;
                } else {
                    //先判断流程中是否有审批人自选，有则选人
                    $result = self::judgeSelfChoose($flow);

                    if ($result === true) {
                        return $this->addAuditPeople($id, $this->post('body'), $flow);
                    } else {
                        $warn = self::start($id, $body, $flow);
                    }
                }
                break;
            // 添加审批人
            case 'addApprover':
                $body = self::validateBody($body);
                if ((!is_array($body))) {
                    $warn = $body;
                } else {
                    return $this->insertBefore($id, $this->post('body'));
                    //return  $this->addAuditPeople($id, $this->post('body'));
                }
                break;
            // 转交审批人
            case 'transfer':
                $body = self::validateBody($body);
                if ((!is_array($body))) {
                    $warn = $body;
                } else {
                    return $this->transferLayer($id, $this->post('body'));
                }
                break;
            // 审批
            case 'approval':
                $body = self::validateBody($body, 'approval');
                if ((!is_array($body))) {
                    $warn = $body;
                } else {
                    return $this->auditLayer($id, $this->post('body'));
                }
                break;
            // 催办
            case 'press':
                $warn = $this->press($id);
                break;
            default:
                $warn = L('audit.table.wei_zhi_cao_zuo');
                break;
        }

        if (!static::isNull($warn)) {
            if (str_contains($warn, '成功')) {
                $_SESSION['warn'] = $warn;
                $json['warn']     = 2;
            } else {
                $json['warn'] = $warn;
            }
        } else {
            $json = [];
        }

        resp:
        return json_encode($json, 320);
    }



    /**
     * 审批记录
     *
     * @param string $table
     * @param string $targetId
     * @return string
     */
    public static function auditRecord(string $table, string $targetId): string
    {
        //数据库查询
        $info  = query($table, " id = '$targetId' ");
        $audit = query('audit', " targetId = '$targetId' order by updateTime desc");
        if (static::isNull($audit['id'])) {
            return false;
        }
        $examine  = (array)json_decode($info['examine'], true);
        $liString = '';
        $x        = 1;
        // 获取本次审核中的结果集
        $result = array_filter($examine, function ($arr) {
            return $arr['state'] == '审核中';
        });
        foreach ($examine as $k => $array) {
            $array['multiType'] = $array['multiType']??'';
            $x++;
            $first = false;
            // 当前进度
            if (in_array($array['state'], ['已通过', '已抄送'])) {
                $style = 'done';
                $now   = '√';
            } elseif (in_array($array['state'], ['已驳回'])) {
                $style = 'done';
                $now   = 'x';
            } else {
                $now = $x;
                // 判断当前流程是否是第一个待审核流程
                if ($array['state'] == '审核中' && $array['id'] == reset($result)['id']) {
                    $style = 'current';
                    $first = true;
                } else {
                    $style = 'none';
                }
            }

            $string = $text = '';
            $y      = 0;
            foreach ($array['stateNode'] as $node) {
                $auditBtn = '';
                if (is_array($node)) {
                    switch ($node['state']) {
                        case '已通过':
                        case '已驳回':
                            $state  = ($node['state'] == '已通过') ? L('audit.table.tong_guo') : L('audit.table.bo_hui');
                            $record = query('backlog', " `stid` = '$node[stid]' AND `workFlow`='已完成' AND `typeId` = '{$audit['id']}' ORDER BY updateTime DESC ");
                            $text   = str_replace(['{{staffName}}', '{{operate}}', '{{flowName}}'], [self::findStaff($node['stid']), $state, $audit['flowName']], L('audit.table.auditRecord')) . (!empty($array['auditFollow'][$node['stid']]) ? '，' . $array['auditFollow'][$node['stid']] : '');
                            break;
                        case '已抄送':
                            $record = query('message', " `stid` = '$node[stid]' AND `typeId` = '{$audit['id']}' ORDER BY time DESC  ");
                            $text   = str_replace(['{{staffName}}', '{{flowName}}'], [self::findStaff($node['stid']), $audit['flowName']], L('audit.table.copyRecord'));
                            break;
                        default:
                            if ((in_array($array['state'], ['已通过', '已驳回']) && $array['multiType'] == '或签') || $audit['workFlow'] == '草稿') {
                                $text = '【' . self::findStaff($node['stid']) . '】';
                                break;
                            }
                            $record = [];
                            $text   = '【' . self::findStaff($node['stid']) . '】' . ($array['form'] == 'approver' ? '审核中' : '待抄送');
                            // 是否催办 处于当前审批节点 且是发起人
                            if ($array['form'] == 'approver' && $array['state'] == '审核中' && $y == 0 && $first === true && $audit['applicantId'] == self::$stid) {
                                $y++;
                                $auditBtn = spanButton([
                                    'name'  => L('audit.table.cui_ban'),
                                    'style' => 'audit-record-btn',
                                    'page'  => 'audit',
                                    'fun'   => 'operate',
                                    'para'  => [
                                        'act' => 'press',
                                        'id'  => $audit['id'],
                                    ],
                                ]);
                            }
                            break;
                    }
                    $record = $record ?? [];
                    if (in_array($array['state'], ['已通过', '已驳回']) && !in_array($node['state'], ['已通过', '已驳回']) && $array['multiType'] == '或签') {
                        $record['updateTime'] = '';
                    }
                    $auditRecord = $record ? '<span class="audit-record-time">' . $record['updateTime'] . '</span>' : '';
                    $string      .= '<p>' . $text . $auditRecord . $auditBtn . '</p>' . self::showAnnex($audit['id'], $node['stid'], '审批记录');
                }
            }
            // 类型
            $type     = $array['form'] == 'approver' ? L('audit.table.shen_he_ren') . '-' . $array['type'] . '-' . $array['multiType'] : L('audit.table.copyStaff');
            $liString .= <<<EOT
            <li>
                <div class="left"><span class="$style">$now</span>$type</div>
                <div class="right">
                    $string
                </div>
            </li>
EOT;
        }
        $startWord    = L('audit.table.start');
        $commitRecord = str_replace(['{{staffName}}', '{{flowName}}'], [$audit['applicant'], $audit['flowName']], L('audit.table.commitRecord'));
        return empty($info['examine']) ? '' : <<<EOT
        <div class="audit-record">
            <ul class="audit-record-ul">
                <li>
                    <div class="left "><span class="done">√</span>$startWord</div>
                    <div class="right"><p>$commitRecord<span class="audit-record-time">{$audit['commitTime']}</span></p><div>
                </li>
                $liString
            </ul>
        </div>
EOT;
    }

    /**
     * 文件列表展示
     *
     * @param string $id 对象ID
     * @param string $stid 审批人
     * @param string $type 对象类型
     * @return string
     */
    public static function showAnnex(string $id, string $stid, $type = ''): string
    {
        $where = '';
        if ($type) {
            $where .= " and target = '$type'";
        }
        $fileCollection = '';
        $result         = find(array('table' => " file", "where" => "stid = '$stid' and targetId !='' and targetId = '$id' {$where} order by time asc"));
        foreach ($result['array'] as $array) {
            $size           = self::formatSize($array['size']);
            $title          = $array['name'];
            $fileCollection .= "
        <div class='file_block_bg'>
                <img src='" . root . "img/control/annex.svg'>
                <div class='file_block_right'>
                    <div class='file_block_right_text' title='$title'>$title</div>
                    <div><span class='title-color'>$size</span>" . fileUploadClass::view($array['src'], true, $array['name']) . "</div>
                </div>
        </div>
        ";
        }
        return $fileCollection ? "<div class='file_block_bg_parent'>" . $fileCollection . "</div>" : '';
    }

    /**
     * 选择审批人
     *
     * @return bool|string
     */
    public function chooseStaff()
    {
        $flow  = $this->post('flow') ? self::encryptDecrypt($this->post('flow'), true) : '';
        $flow  = $flow ? json_decode($flow, true) : [];
        $where = '';
        foreach ($flow as $array) {
            if ($array['type'] == '审批人自选') {
                if ($array['value'] == '指定范围') {
                    $where .= " and stid in ('" . implode("','", explode(';', $array['staff[]'])) . "')";
                }
                break;
            }
        }
        //生成表单
        $html = $this->layerEdit(array(
            "table"     => array(
                array(
                    L('audit.table.auditStaff') . "：" => selectMultiple(array('name' => 'chooseStid', 'title' => L('audit.table.qing_xuan_ze'), 'table' => "staff", 'where' => " state in ('转正','试用')" . $where, 'sqlId' => 'stid', 'sqlField' => 'name')),
                ),
            ),
        ));
        //返回
        return $this->layer(array(
            "title" => L('audit.table.xuan_ze'),
            'winFix' => true,
            'zindex'=>20,
            "height" => 200,
            "width" => 600,
            "html" => $html,
            'button' => "<input onclick=\"chooseStaff()\" type='button' class='button' value='" . L('audit.table.que_ren_ti_jiao') . "'>"
        ));
    }

    /**
     * 组成审批人部分
     *
     * @return bool|string
     */
    public function assembly(): bool|string
    {
        $stid = $this->post('stid');
        if (empty($stid)) {
            $json['warn'] = L('audit.table.qxzspr');
        } else {
            $staff        = query('staff', "stid = '$stid'");
            $src          = root . $staff['ico'];
            $json['warn'] = 2;
            $json['html'] = <<<efo
                                    <li>
                                         <div class="li-block">
                                             <img class="li-ico" src="$src" alt="li-ico">
                                             <a href='javascript:void(0)' onclick="deletePeople(this)"><div><span class='u-icon-delete'><i></i></span></div></a>
                                             <div>{$staff['name']}</div>
                                             <input type="hidden" name="stid[]" value="{$staff['stid']}">
                                         </div>
                                    </li>
efo;
        }
        return json_encode($json, 320);
    }

    /**
     * 添加审批人弹窗
     *
     * @return bool|string
     */
    public function addAuditPeople($id, $body, $flow)
    {
        $flow       = json_encode($flow, 320);
        $node       = self::encryptDecrypt($flow);
        $peopleHtml = <<<efo
                            <div class="people-block">
                                 <ul>
                                 <li>
                                     <div class="add-button-li" onclick='layer("audit","chooseStaff",{id:"$id",body:"$body",flow:"$node"})'>+</div>
                                 </li>
                            </ul>
                            </div>
                            <input name="body" type="hidden" value="$body">
                            <input name="id" type="hidden" value="$id">
  <input name="flow" type="hidden" value='$flow'>
efo;

        //表单名称
        $form = $this->get('cla') . ucwords($this->get('fun')) . "Form";
        //生成表单
        $html = $this->layerEdit(array(
            "table"     => array(
                array(
                    L('audit.table.auditStaff') . "：" => $peopleHtml,
                ),
            ),
        ));
        $html .= <<<efo
<script>
function deletePeople(e){
    $(e).parent().parent().remove();
}
function chooseStaff(){
   let stid =  $("[name='chooseStid']").val();
   let flag = true;
   $("[name='stid[]']").each(function() {
      let thisStid = $(this).val();
      if (stid===thisStid){
         flag = false;
      }
   })
   if (flag){
        $.post(root+'control/adIndex.html?cla=audit&fun=assembly',{stid:stid},function (res){
       if (res.warn ===2){
           $(".add-button-li").parent().before(res.html);
       }
     },'json')
   }
    $('#auditChooseStaff').remove()
}
</script>
efo;
        //返回
        return $this->layer(array(
            "title" => L('audit.table.tjspr'),
            "height" => 300,
            "html" => $html,
            'button' => "<input onclick=\"subForm('" . $form . "','" . root . "control/adIndex.html?cla=audit&fun=addAuditPeopleEdit')\" type='button' class='button' value='" . L('audit.table.que_ren_ti_jiao') . "'>"
        ));
    }

    /**
     * 添加审批人编辑
     */
    public function addAuditPeopleEdit(): bool|string
    {
        $staffId = $this->post('stid');
        $id      = $this->post('id');
        $body    = $this->post('body');
        $flow    = $_POST['flow'];//审批流程
        $body    = self::validateBody($body);
        $flow    = $flow ? json_decode($flow, true) : [];
        $flag    = false;
        foreach ($flow as $array) {
            if ($array['type'] == '审批人自选' && $array['state'] == '审核中' && $array['form'] == 'approver') {
                $flag = true;
                break;
            }
        }
        if (empty($staffId) || !is_array($staffId)) {
            $json['warn'] = L('audit.table.wzdspr');
        } elseif (!$flag) {
            $json['warn'] = L('audit.table.csplczmzsprzx');
        } else {
            $staffId   = array_unique($staffId);//去除重复
            $staffName = [];                    //员工姓名组装
            $stateBox  = [];                    //状态组装
            foreach ($staffId as $stid) {

                $staff       = query('staff', " stid = '$stid'");
                $staffName[] = $staff['name'];
                $stateBox    = self::updateStateNode($stateBox, '审核中', $stid, true);
            }
            foreach ($flow as $k => $array) {
                if ($array['type'] == '审批人自选' && $array['form'] == 'approver' && $array['state'] == '审核中') {
                    $array['type']      = '指定成员';
                    $array['staff[]']   = implode(';', $staffId);
                    $array['staffName'] = implode(',', $staffName);
                    $array['stateNode'] = $stateBox;
                    $array['state']     = '审核中';
                    $flow[$k]           = $array;
                    break;
                }
            }
            $warn = self::start($id, $body, $flow);
            if ($warn !== true) {
                $json['warn'] = $warn;
            } else {
                $json['warn']     = 2;
                $_SESSION['warn'] = L('audit.table.tjcg');
            }
            // 添加审批人，自定义返回链接
            if($json['warn'] == 2 && isset($body['href']) && $body['href']){
                $json['href'] = $body['href'];
            }
        }
        return json_encode($json, 320);
    }


    /**
     * 生成已处理待办
     */
    public static function generateDoneTip($auditStaff, $flowName, $auditId, $text)
    {
        if (is_array($auditStaff)) {
            foreach ($auditStaff as $stid) {
                static::insert(array(
                    'table' => 'backlog',
                    'field' => array(
                        'id'       => self::getId(),
                        "coid"     => self::$coid,
                        "stid"     => $stid,
                        "type"     => $flowName,
                        "typeId"   => $auditId,
                        "text"     => $text,
                        "startDay" => date('Y-m-d'),
                        'workFlow' => '已完成',
                    ),
                ));
            }
        }
    }

    /**
     * 寻找下一审批人
     *
     * @param        $flow
     * @param string $type
     * @param string $chooseStid
     * @return array
     */
    public static function findAuditPeople($flow, string $type = '', string $chooseStid = ''): array
    {
        $staffName    = [];   //审批人姓名数组
        $staffId      = [];   //审批人ID数组
        $nodeIsEnd    = false;//节点审批完成标志  true:完成
        $isEnd        = false;//判断接下来是否还有审批
        $completeNode = 0;
        $auditType    = '';//当前审批类型 //主要用于判断是否是审批人自选
        foreach ($flow as $k => $array) {
            if ($array['form'] == 'approver' && $array['type'] != '审批人自选') {
                $array['isAuto'] = $array['isAuto'] ?? '否';
                if ($array['isAuto'] === '是' && $array['state'] == '审核中') {
                    //自动审批节点
                    //此审批节点已通过
                    $flow[$k]['state'] = '已通过';
                    $nodeIsEnd         = true;
                    $staffName         = [];//员工姓名组装
                    $staffId           = [];
                    $stateNode         = [];
                    $auditStaff        = explode(';', $array['staff[]']);//当前节点的审核人数组
                    $auditStaff        = array_filter($auditStaff);
                    foreach ($auditStaff as $index => $stid) {
                        if ($array['multiType'] == '或签') {
                            $stateNode[] = [
                                'stid'  => $stid,
                                'state' => $index == 0 ? '已通过' : '审核中',
                            ];
                        } else {
                            $stateNode[] = [
                                'stid'  => $stid,
                                'state' => '已通过',
                            ];
                        }
                    }
                    $flow[$k]['state']     = '已通过';
                    $flow[$k]['stateNode'] = $stateNode;
                } elseif ($array['state'] == '审核中') {
                    if (empty($array['staff[]'])) {
                        //此审批节点已通过
                        $flow[$k]['state'] = '已通过';
                        $nodeIsEnd         = true;
                        $staffName         = [];//员工姓名组装
                        $staffId           = [];
                    } else {
                        $auditStaff = explode(';', $array['staff[]']);//当前节点的审核人数组
                        $auditStaff = array_filter($auditStaff);
                        $stateNode  = $array['stateNode'];//每个审批人审批状态集合
                        $stateBox   = [];                 //状态组装
                        if ($type == '转交') {
                            foreach ($auditStaff as $stid) {
                                if ($stid == self::$stid) {
                                    $stid = $chooseStid;//转交人覆盖当前人
                                }
                                if ($chooseStid == $stid) {
                                    //如果转交的人已审批过，则需要再审批一次
                                    $stateBox[] = [
                                        'stid'  => $stid,
                                        'state' => '审核中',
                                    ];
                                } else {
                                    $stateBox[] = [
                                        'stid'  => $stid,
                                        'state' => self::returnState($stateBox, $stid) ?: '审核中',
                                    ];
                                }
                                $staff       = query('staff', " stid = '$stid'");
                                $staffName[] = $staff['name'];
                                $staffId[]   = $stid;
                            }
                        } else {
                            $stateBox  = $stateNode;
                            $staffId   = $auditStaff;
                            $staffName = explode(',', $array['staffName']);
                        }

                        $stName             = array_unique(array_filter($staffName));
                        $staffId            = array_unique(array_filter($staffId));//去重
                        $array['staff[]']   = implode(';', $staffId);
                        $array['staffName'] = implode(',', $stName);
                        $array['stateNode'] = $stateBox;
                        $flow[$k]           = $array;

                        $state_res = self::returnStateCollection($stateBox);
                        if (in_array($array['multiType'], ['会签', '依次审批']) && in_array('审核中', $state_res)) {
                            //会签和依次审批必须全部审批完成
                            if ($array['multiType'] == '依次审批') {
                                $staffName = [];//员工姓名组装
                                $staffId   = [];
                                //查找当前审批人
                                foreach ($stateBox as $item) {
                                    if ($item['state'] == '审核中') {
                                        $staffName[] = self::findStaff($item['stid']);
                                        $staffId[]   = $item['stid'];
                                        break;
                                    }
                                }
                            } elseif ($array['multiType'] == '会签') {
                                $staffName = [];//员工姓名组装
                                $staffId   = [];
                                //查找当前审批人
                                foreach ($stateBox as $item) {
                                    if ($item['state'] == '审核中') {
                                        $staffName[] = self::findStaff($item['stid']);
                                        $staffId[]   = $item['stid'];
                                    }
                                }
                            }
                            break;
                        } elseif (in_array($array['multiType'], ['或签']) && !in_array('已通过', $state_res)) {
                            //或签至少一人审批完成
                            break;
                        } else {
                            //此审批节点已通过
                            $flow[$k]['state'] = '已通过';
                            $nodeIsEnd         = true;
                            $staffName         = [];//员工姓名组装
                            $staffId           = [];
                        }
                    }
                } else {
                    //此审批节点已通过
                    $nodeIsEnd = true;
                }
            } elseif ($array['form'] == 'approver' && $array['type'] == '审批人自选') {
                $staffName = [];//员工姓名组装
                $staffId   = [];
                $auditType = '审批人自选';
                break;
            }
            $completeNode++;
        }

        if ($completeNode == count($flow) && $nodeIsEnd) {
            //此节点已结束且当前处于最后一节点
            $isEnd = true;
        }
        return ['flow' => $flow, 'auditType' => $auditType, 'staffId' => array_filter($staffId), 'staffName' => array_filter($staffName), 'nodeIsEnd' => $nodeIsEnd, 'isEnd' => $isEnd];
    }

    /**
     * 审批弹窗
     */
    public function auditLayer($id, $body): bool|string
    {
        //生成表单
        $html = $this->layerEdit(array(
            "table"     => array(
                array(
                    must . L('audit.table.auditResult') . "：" => radio(array('name' => 'state', 'checked' => '已通过', 'value' => ['已通过' => L('audit.table.tong_guo'), '草稿' => L('audit.table.bo_hui')])) . $this->js($body, $id),
                ),
                array(
                    L('audit.table.text') . "：" => textarea(array('name' => 'text', 'class' => 'textarea')),
                ),
                array(
                    "附件：" => fileUploadClass::addFileComponent($id, '审批记录', 'myApproved', 'auditOperateForm'),
                ),
            ), 'hidden' => hidden(array('name' => 'body', 'value' => $body)) . hidden(array('name' => 'id', 'value' => $id)),
        ));
        //返回
        return $this->layer(array(
            "title" => L('audit.table.shen_pi'),
            "height" => 400,
            "width" => 858,
            "html" => $html,
            'button' => "<input onclick=\"subForm('auditOperateForm','" . root . "control/adIndex.html?cla=audit&fun=auditLayerEdit')\" type='button' class='button' value='" . L('audit.table.que_ren_ti_jiao') . "'>"
        ));
    }


    public function js($body, $id)
    {
        $body    = self::validateBody($body);
        $info    = query($body['table'], " id = '$id'");
        $examine = (array)json_decode($info['examine'], true);
        $index   = 1;
        $content = <<<eof
 <div class="node-area">
        <div class="node-area-pot active" data-id="start">$index</div>
        <div class="node-area-text">发起</div>
</div>
eof;
        foreach ($examine as $array) {
            if ($array['form'] == 'approver' && $array['state'] == '已通过') {
                //已审核过的节点
                $index++;
                $text    = $array['type'] . '-' . $array['multiType'];
                $stidArr = [];
                foreach ($array['stateNode'] as $stateNode) {
                    if ($stateNode['state'] == '已通过') {
                        $stidArr[] = self::findStaff($stateNode['stid']);
                    }
                }
                if (count($stidArr) > 0) {
                    $text .= "-" . implode(',', $stidArr);
                }
                $content .= <<<eof
<div class="node-area width1">
        <div class="node-area-line"></div>
</div>
<div class="node-area">
    <div class="node-area-pot" data-id="$array[id]">$index</div>
    <div class="node-area-text">$text</div>
</div>
eof;

            }
        }
        return <<<eof
<div class="node-div hide">
    $content
</div>
 <input type="hidden" name="flowId" value="start">
<style>
.node-div{margin: 10px 0}
.node-area{display: inline-block;width: 150px;text-align: center;vertical-align:top;margin: 10px 0;cursor: pointer}
.node-area .node-area-pot{border: 1px solid rgb(128,128,128);border-radius: 50%;width: 30px;height: 30px;line-height: 30px;text-align: center;margin: 0 auto}
.node-area .node-area-text{line-height: normal;height: 40px;overflow: auto;}
.node-area .node-area-line{border-bottom: 1px solid;margin-top: 15px;margin-left: -50px;width: 98px;}
.node-div .active{background-color: rgb(53, 119, 255);color: white;border-color: rgb(53, 119, 255)}
.width1{width: 1px}
</style>
<script>
$(".node-area-pot").click(function() {
   $(".node-div .active").removeClass("active");
   $(this).addClass("active");
   $("[name='flowId']").val($(this).data('id'))
})
$("[name='auditOperateForm'] input[name='state']").click(function() {
    if ($(this).val() === '草稿'){
        $(".node-div").show()
    }else{
        $(".node-div").hide()
    }
})
</script>
eof;

    }


    /**
     * 添加流程名称作为条件
     *
     * @param $flowName
     * @param string $orderNo
     * @return string
     */
    public static function flowWhere($flowName, $orderNo = ''): string
    {
        $where = '';
        if ($flowName) {
            $where .= " and flowName = '$flowName'";
        }
        if ($orderNo) {
            $where .= " and orderNo = '$orderNo'";
        }
        return $where;
    }

    /**
     * 更新状态节点
     */
    public static function updateStateNode($node, $state, $stid, $insert = false): array
    {
        $isExist = false;
        foreach ($node as $k => $item) {
            if ($item['stid'] == $stid) {
                $isExist           = true;
                $node[$k]['state'] = $state;
                break;
            }
        }
        if ($insert && !$isExist) {
            //判断当前是否已存在此人
            $node[] = [
                'stid'  => $stid,
                'state' => $state,
            ];
        }
        return $node;
    }

    /**
     * 审核编辑
     */
    public function auditLayerEdit()
    {
        $id = $this->post('id');//对应表ID
        //附件
        $fileIdArr = $this->post('fileId');

        $flowId     = $this->post('flowId');//审核节点ID
        $text       = $this->post('text'); //备注
        $state      = $this->post('state');//审批状态
        $body       = $this->post('body');
        $body       = self::validateBody($body);
        $targetInfo = query($body['table'], " id = '$id'");
        $where      = self::flowWhere($body['name'] ?? '', $targetInfo['orderNo'] ?? '');
        $audit      = query('audit', " targetId = '$id' $where order by updateTime desc");
        if (empty($audit['id'])) {
            $json['warn'] = L('audit.table.wzdcspjl');
        } elseif (!in_array(self::$stid, explode(',', $audit['approverId']))) {
            $json['warn'] = L('audit.table.nbsdqshrbnshcjl');
        } elseif (empty($this->post('body'))) {
            $json['warn'] = L('audit.table.wzdqqcs');
        } else {

            $flow = json_decode($targetInfo['examine'], true);
            if (!is_array($flow) || empty($flow)) {
                $json['warn'] = L('audit.table.wzdsplc');
            } elseif ($state == '草稿') {
                foreach ($flow as $k => $array) {
                    if ($array['state'] == '审核中' && $array['form'] == 'approver') {
                        $approver = explode(';', $array['staff[]']);
                        if (!in_array(self::$stid, (array)$approver)) {
                            $json['warn'] = '您已审批过了，请勿重复操作!';
                            goto resp;
                        }
                        $array['stateNode']                = self::updateStateNode($array['stateNode'], '已驳回', self::$stid);
                        $array['auditFollow'][self::$stid] = $text;
                        $array['state']                    = '已驳回';
                        $flow[$k]                          = $array;
                        break;
                    }
                }

                $field            = [
                    'examine' => json_encode($flow, 320),
                ];
                $field['examine'] = addcslashes($field['examine'], '\\');
                if (empty($flowId) || !str_contains($field['examine'], $flowId)) {
                    $flowId = 'start';//如果未找到此ID,则默认驳回到发起人
                }

                if ($flowId == 'start') {
                    //驳回到发起人
                    if (is_array($body['field'])) {
                        foreach ($body['field'] as $item) {
                            $field[$item] = $body['value'][$item][0];
                        }
                    }
                    //驳回
                    $json['warn'] = update(array('table' => $body['table'], 'field' => $field, 'where' => " id = '$id'"));
                    if ($json['warn'] == '更新成功') {
                        //更新待办
                        backlogEnd(array(
                            "stid"   => $this->control['stid'],
                            "typeId" => $audit['id'],
                        ));
                        //清除未处理的待办
                        $this->clearBackLog($audit['id']);
                        //给发起人发送消息
                        message(array(
                            "stid"   => $audit['applicantId'],
                            "type"   => $audit['flowName'],
                            "typeId" => $audit['id'],
                            "text"   => str_replace(['{{flowName}}', '{{text}}'], [$audit['flowName'], $text ?: '无'], L('audit.table.refuseMsg')),
                        ));
                        //添加审批记录
                        auditingFollow([
                            "type"      => $audit['flowName'],
                            "typeId"    => $audit['id'],
                            "text"      => "【{$this->control['name']}】驳回了【{$audit['flowName']}】" . ($text ? '，备注：' . $text : ''),
                            'remark'    => $text,
                            'staffName' => $this->control['name'],
                            'job'       => self::findStaffDepartment(self::$stid) . '-' . $this->controlJob['name'],
                        ]);

                        //更新审批表
                        update(array('table' => 'audit', 'field' => ['workFlow' => '草稿', 'approver' => '', 'approverId' => '', 'commitTimePrevious' => '', 'commitTime' => ''], 'where' => " id = '$audit[id]'"));
                        $json['warn']     = 2;
                        $_SESSION['warn'] = L('audit.table.bhcg');
                    }
                } else {
                    //驳回到指定审核节点
                    $afterFlag = false;
                    foreach ($flow as $k => $array) {
                        if ($array['form'] == 'approver' && ($flowId == $array['id'] || $afterFlag)) {
                            $afterFlag      = true;
                            $array['state'] = '审核中';
                            unset($array['auditFollow']);
                            foreach ($array['stateNode'] as $index => $item) {
                                $array['stateNode'][$index]['state'] = '审核中';
                            }
                        }
                        $flow[$k] = $array;
                    }
                    $field        = [
                        'examine' => json_encode($flow, 320),
                    ];
                    $json['warn'] = update(array('table' => $body['table'], 'field' => $field, 'where' => " id = '$id'"));
                    if ($json['warn'] == '更新成功') {
                        $this->rejectTheNode($flow, $audit, $text);
                        $json['warn']     = 2;
                        $_SESSION['warn'] = L('audit.table.bhcg');
                    }
                }

            } else {
                //通过
                //寻找审批顺序
                $auditOrderBy = $this->findAuditOrder($flow);
                $nowAuditType = '';//当前审批类型
                foreach ($flow as $k => $array) {
                    if ($array['state'] == '审核中' && $array['form'] == 'approver') {
                        $approver = explode(';', $array['staff[]']);
                        if (!in_array(self::$stid, (array)$approver)) {
                            $json['warn'] = '您已审批过了，请勿重复操作!';
                            goto resp;
                        }
                        $nowAuditType                      = $array['multiType'];
                        $array['stateNode']                = self::updateStateNode($array['stateNode'], '已通过', self::$stid);
                        $array['auditFollow'][self::$stid] = $text;
                        if ($array['multiType'] == '或签') {
                            $array['state'] = '已通过';
                        } elseif (in_array($array['multiType'], ['会签', '依次审批'])) {
                            if (!in_array('审核中', self::returnStateCollection($array['stateNode']))) {
                                //全部已通过
                                $array['state'] = '已通过';
                            } else {
                                $array['state'] = '审核中';
                            }
                        }
                        $flow[$k] = $array;
                        break;
                    }
                }


                $result           = self::findAuditPeople($flow);
                $field            = [
                    'examine' => json_encode($result['flow'], 320),
                ];
                $field['examine'] = addcslashes($field['examine'], '\\');
                if ($result['isEnd']) {
                    $field['passTime'] = $this->time;
                    //更新状态
                    if (is_array($body['field'])) {
                        foreach ($body['field'] as $item) {
                            $field[$item] = $body['value'][$item][1];
                        }
                    }
                }

                $json['warn'] = static::update(array('table' => $body['table'], 'field' => $field, 'where' => " id = '$id'"));
                if ($json['warn'] == '更新成功') {
                    //更新当前审批人的待办
                    backlogEnd(array(
                        "stid"   => $this->control['stid'],
                        "typeId" => $audit['id'],
                    ));

                    if ($nowAuditType == '或签') {
                        //清除其他或签人的待办事项
                        $auditStaff = explode(',', $audit['approverId']);
                        foreach ($auditStaff as $stid) {
                            if ($stid != $this->control['stid'] && $stid) {
                                delete(array('table' => 'backlog', 'where' => "typeId = '$audit[id]' and stid = '$stid' and workFlow = '待处理'"));
                            }
                        }
                    }
                    //添加审批记录
                    auditingFollow([
                        "type"      => $audit['flowName'],
                        "typeId"    => $audit['id'],
                        "text"      => "【{$this->control['name']}】通过了【{$audit['flowName']}】" . ($text ? '，备注：' . $text : ''),
                        'remark'    => $text,
                        'staffName' => $this->control['name'],
                        'job'       => self::findStaffDepartment(self::$stid) . '-' . $this->controlJob['name'],
                    ]);
                    if ($auditOrderBy['auditNode'] == 1 && $auditOrderBy['staffNode'] == 1) {
                        //第一次审批
                        self::call($body['process']['before']['cla'], $body['process']['before']['fun'], $body['process']['before']['data'] ?? []);
                    }
                    if ($result['nodeIsEnd']) {
                        //当前节点完成
                        //判断是否有抄送人，发送消息
                        $copyStaff = self::findCopy($result['flow'], $id, $body['table']);
                        self::batchMessage($copyStaff, $audit['id'], str_replace(['{{deptName}}', '{{staffName}}', '{{name}}'], [$audit['applicantDepartment'], $audit['applicant'], $audit['flowName']], L('audit.table.copySee')));
                    }
                    if ($result['isEnd']) {
                        //当前是最后一次审批
                        //审核完成调用方法
                        self::call($body['process']['after']['cla'] ?? '', $body['process']['after']['fun'] ?? '', $body['process']['after']['data'] ?? []);
                        //给发起人发送已完成的消息
                        message(array(
                            "stid"   => $audit['applicantId'],
                            "type"   => $audit['flowName'],
                            "typeId" => $audit['id'],
                            "text"   => str_replace(['{{flowName}}'], [$audit['flowName']], L('audit.table.auditPassMsg')),
                        ));
                    } elseif ($result['auditType'] == '审批人自选') {
                        self::batchMessage([$audit['applicantId']], $audit['id'], str_replace(['{{flowName}}'], [$audit['flowName']], L('audit.table.needAuditPeople')));
                    } else {
                        //给下一审批人添加待办
                        self::sendTip($result['staffId'], $audit['id'], str_replace(['{{deptName}}', '{{staffName}}', '{{name}}'], [$audit['applicantDepartment'], $audit['applicant'], $audit['flowName']], L('audit.table.commitAudit')));

                        self::findAutoNode($result['flow'], $audit['flowName'], $audit['id'], str_replace(['{{deptName}}', '{{staffName}}', '{{name}}'], [$audit['applicantDepartment'], $audit['applicant'], $audit['flowName']], L('audit.table.commitAudit')));
                    }

                    //更新审批表
                    $field = [
                        'approver'   => implode(',', $result['staffName']),
                        'workFlow'   => $result['isEnd'] ? '已通过' : '审核中',
                        'approverId' => implode(',', $result['staffId']),
                    ];
                    if ($result['nodeIsEnd']) {
                        $field['commitTimePrevious'] = $this->time;//更新上节点提交时间
                    }
                    //更新审批表
                    update(array('table' => 'audit', 'field' => $field, 'where' => "id = '$audit[id]'"));

                    $json['warn']     = 2;
                    $_SESSION['warn'] = L('audit.table.spcg');
                }
            }
        }
        //添加主表ID到附件表
        if (is_array($fileIdArr) && $json['warn'] == 2) {
            update(array('table' => 'file', 'field' => ['targetId' => $audit['id']], 'where' => " targetId = '' and id in ('" . implode("','", $fileIdArr) . "')"));
        }
        resp:
        return json_encode($json, 320);
    }


    public function rejectTheNode($flow, $audit, $text)
    {

        $result = self::findAuditPeople($flow);
        //更新当前审批人的待办
        backlogEnd(array(
            "stid"   => $this->control['stid'],
            "typeId" => $audit['id'],
        ));
        //清除未处理的待办
        $this->clearBackLog($audit['id']);
        //添加审批记录
        auditingFollow([
            "type"      => $audit['flowName'],
            "typeId"    => $audit['id'],
            "text"      => "【{$this->control['name']}】驳回了【{$audit['flowName']}】到指定节点" . ($text ? '，备注：' . $text : ''),
            'remark'    => $text,
            'staffName' => $this->control['name'],
            'job'       => self::findStaffDepartment(self::$stid) . '-' . $this->controlJob['name'],
        ]);

        if ($result['auditType'] == '审批人自选') {
            self::batchMessage([$audit['applicantId']], $audit['id'], str_replace(['{{flowName}}'], [$audit['flowName']], L('audit.table.needAuditPeople')));
        } else {
            //给下一审批人添加待办
            self::sendTip($result['staffId'], $audit['id'], '【' . $audit['applicantDepartment'] . '】-【' . $audit['applicant'] . '】提交的【' . $audit['flowName'] . '】被【' . self::findStaff(self::$stid) . '】驳回到您的节点，需要您重新审批' . ($text ? '，备注：' . $text : ''));
            self::findAutoNode($result['flow'], $audit['flowName'], $audit['id'], str_replace(['{{deptName}}', '{{staffName}}', '{{name}}'], [$audit['applicantDepartment'], $audit['applicant'], $audit['flowName']], L('audit.table.commitAudit')));
        }
        //更新审批表
        $field = [
            'approver'   => implode(',', $result['staffName']),
            'workFlow'   => $result['isEnd'] ? '已通过' : '审核中',
            'approverId' => implode(',', $result['staffId']),
        ];
        if ($result['nodeIsEnd']) {
            $field['commitTimePrevious'] = $this->time;//更新上节点提交时间
        }
        //更新审批表
        update(array('table' => 'audit', 'field' => $field, 'where' => "id = '$audit[id]'"));
    }


    /**
     * 获取当前审核人的审批状态
     */
    public static function returnState($array, $stid): string
    {
        foreach ($array as $item) {
            if ($stid == $item['stid']) {
                return $item['state'];
            }
        }
        return '';
    }

    /**
     * 审批人选择插入另一审批人
     */
    public function insertBeforeEdit(): bool|string
    {
        $chooseStid = $this->post('stid');
        $id         = $this->post('id');
        $body       = $this->post('body');
        $body       = self::validateBody($body);
        if (empty($chooseStid)) {
            $json['warn'] = L('audit.table.qxzshr');
        } else {
            $table        = $body['table'];
            $body['name'] = $body['name'] ?? '';
            $info         = query($table, " id = '$id'");
            $where        = self::flowWhere($body['name'], $info['orderNo'] ?? '');
            $audit        = query('audit', " targetId = '$info[id]' $where order by updateTime desc");

            $flow = $info['examine'] ? json_decode($info['examine'], true) : [];
            foreach ($flow as $k => $array) {
                if ($array['form'] == 'approver' && $array['state'] == '审核中') {
                    //当前审批节点
                    $auditStaff = explode(';', $array['staff[]']);
                    $auditStaff = array_unique(array_filter($auditStaff));
                    if ($array['multiType'] == '依次审批') {
                        $newAuditStaff = [];
                        foreach ($auditStaff as $stid) {
                            if ($stid == self::$stid) {
                                $newAuditStaff[] = $chooseStid;
                                $newAuditStaff[] = $stid;
                            }
                            $newAuditStaff[] = $stid;
                        }
                        //插入后的审批人
                        $stateBox = [];
                        foreach ($newAuditStaff as $stid) {
                            $stateBox = self::updateStateNode($stateBox, self::returnState($array['stateNode'], $stid) ?: '审核中', $stid, true);
                        }
                        $array['stateNode'] = $stateBox;
                        $array['staff[]']   = implode(';', $newAuditStaff);
                    } else {
                        $auditStaff[] = $chooseStid;
                        foreach ($auditStaff as $stid) {
                            $array['stateNode'] = self::updateStateNode($array['stateNode'], self::returnState($array['stateNode'], $stid) ?: '审核中', $stid, true);
                        }
                        $array['staff[]'] = implode(';', $auditStaff);
                    }
                    $flow[$k] = $array;
                    break;
                }
            }

            //寻找下一审批人
            $result = self::findAuditPeople($flow);
            $field  = [
                'examine' => json_encode($result['flow'], 320),
            ];

            $json['warn'] = update(array('table' => $table, 'field' => $field, 'where' => " id = '$info[id]'"));
            if ($json['warn'] == '更新成功') {
                $staff = query('staff', "stid = '$chooseStid'");
                //添加审批记录
                auditingFollow([
                    "type"      => $audit['flowName'],
                    "typeId"    => $audit['id'],
                    "text"      => "【{$this->control['name']}】插入了新的审批人【{$staff['name']}】",
                    'remark'    => '',
                    'staffName' => $this->control['name'],
                    'job'       => self::findStaffDepartment(self::$stid) . '-' . $this->controlJob['name'],
                ]);
                //更新审批表
                $field = [
                    'approver'   => implode(',', $result['staffName']),
                    'workFlow'   => $result['isEnd'] ? '已通过' : '审核中',
                    'approverId' => implode(',', $result['staffId']),
                ];
                if ($result['nodeIsEnd']) {
                    $field['commitTimePrevious'] = $this->time;//更新上节点提交时间
                }

                $warn = update(array('table' => 'audit', 'field' => $field, 'where' => "id = '$audit[id]'"));
                if ($warn == '更新成功') {
                    //待办提醒
                    self::sendTip($result['staffId'], $audit['id'], str_replace(['{{deptName}}', '{{staffName}}', '{{name}}'], [$audit['applicantDepartment'], $audit['applicant'], $audit['flowName']], L('audit.table.commitAudit')));
//                    self::findAutoNode($result['flow'],$audit['flowName'],$audit['id'],"【{$audit['applicantDepartment']}】-【{$audit['applicant']}】提交的【{$audit['flowName']}】需要您审批");
                }
                //更新待办
                backlogEnd(array(
                    "stid"   => $this->control['stid'],
                    "typeId" => $audit['id'],
                ));
                $_SESSION['warn'] = L('audit.table.add_success');
                $json['warn']     = 2;
            }
        }
        return json_encode($json, 320);
    }

    /**
     * 在当前审批人之前插入一人
     */
    public function insertBefore($id, $body)
    {
        //生成表单
        $html = $this->layerEdit(array(
            "table"     => array(
                array(
                    must . L('audit.table.auditStaff') . "：" => selectMultiple(array('name' => 'stid', 'title' => L('audit.table.qing_xuan_ze'), 'sqlId' => 'stid', 'sqlField' => 'name', 'table' => "staff", 'where' => " state in ('试用','转正') and stid !='{$this->control['stid']}'")),
                ),
            ), 'hidden' => hidden(array('name' => 'body', 'value' => $body)) . hidden(array('name' => 'id', 'value' => $id)),
        ));
        //返回
        return $this->layer(array(
            "title" => L('audit.table.xuan_ze'),
            'winFix' => true,
            "height" => 217,
            "width" => 600,
            "html" => $html,
            'button' => "<input onclick=\"subForm('auditOperateForm','" . root . "control/adIndex.html?cla=audit&fun=insertBeforeEdit')\" type='button' class='button' value='" . L('audit.table.que_ren_ti_jiao') . "'>"
        ));
    }

    /**
     * 找抄送人
     *
     * @param array $flow 审批流程
     * @param       $targetId
     * @param       $table
     * @return array
     */
    public static function findCopy(array $flow, $targetId, $table): array
    {
        $copyStaff = [];//抄送人；
        foreach ($flow as $k => $array) {
            if ($array['form'] == 'approver') {
                if ($array['state'] == '审核中') {
                    break;
                } else {
                    //已通过
                    $copyStaff = [];
                }
            }
            if ($array['form'] == 'notifier') {
                //抄送
                $copyPeople = explode(';', $array['staff[]']);
                $copyStaff  = array_merge($copyStaff, $copyPeople);
                $copyStaff  = array_unique(array_filter($copyStaff));
                foreach ($copyStaff as $stid) {
                    $array['stateNode'] = self::updateStateNode($array['stateNode'], '已抄送', $stid);
                }
                $array['state'] = '已抄送';
            }
            $flow[$k] = $array;
        }
        update(array('table' => $table, 'field' => ['examine' => json_encode($flow, 320)], 'where' => " id = '$targetId'"));
        return array_unique($copyStaff);
    }

    /**
     * 清除掉未处理的待办
     *
     * @param string $id 我的审批表ID
     */
    public function clearBackLog(string $id)
    {
        delete(array('table' => 'backlog', 'where' => "typeId = '$id' and workFlow = '待处理'"));
    }

    /**
     * 转交弹窗
     */
    public function transferLayer($id, $body): bool|string
    {
        //生成表单
        $html = $this->layerEdit(array(
            "table"     => array(
                array(
                    L('audit.table.tip') . "：" => L('audit.table.zjhjyzjrdwspclc'),
                ),
                array(
                    must . L('audit.table.transTo') . "：" => selectMultiple(array('name' => 'stid', 'title' => L('audit.table.qing_xuan_ze'), 'sqlId' => 'stid', 'sqlField' => 'name', 'table' => "staff", 'where' => " state in ('试用','转正') and stid !='{$this->control['stid']}'")),
                ),
            ), 'hidden' => hidden(array('name' => 'body', 'value' => $body)) . hidden(array('name' => 'id', 'value' => $id)),
        ));
        //返回
        return $this->layer(array(
            "title" => L('audit.table.zhuan_jiao'),
            'winFix' => true,
            "height" => 217,
            "width" => 600,
            "html" => $html,
            'button' => "<input onclick=\"subForm('auditOperateForm','" . root . "control/adIndex.html?cla=audit&fun=transferLayerEdit')\" type='button' class='button' value='" . L('audit.table.que_ren_ti_jiao') . "'>"
        ));
    }

    /**
     * 转交
     */
    public function transferLayerEdit(): bool|string
    {
        $chooseStid = $this->post('stid');
        $id         = $this->post('id');
        $body       = $this->post('body');
        $body       = self::validateBody($body);
        if (empty($chooseStid)) {
            $json['warn'] = L('audit.table.qxzzjr');
        } else {
            $table        = $body['table'];
            $info         = query($table, " id = '$id'");
            $body['name'] = $body['name'] ?? '';
            $where        = self::flowWhere($body['name'], $info['orderNo'] ?? '');
            $audit        = query('audit', " targetId = '$info[id]' $where order by updateTime desc");

            $flow = $info['examine'] ? json_decode($info['examine'], true) : [];
            //寻找下一审批人
            $result = self::findAuditPeople($flow, '转交', $chooseStid);
            $field  = [
                'examine' => json_encode($result['flow'], 320),
            ];
            if ($result['isEnd']) {
                if (is_array($body['field'])) {
                    foreach ($body['field'] as $item) {
                        $field[$item] = $body['value'][$item][0];
                    }
                }
            }

            $json['warn'] = update(array('table' => $table, 'field' => $field, 'where' => " id = '$info[id]'"));
            if ($json['warn'] == '更新成功') {
                if ($result['isEnd']) {
                    //审核完成调用方法
                    self::call($body['process']['after']['cla'], $body['process']['after']['fun'], $body['process']['after']['data']);
                    //给发起人发送已完成的消息
                    message(array(
                        "stid"   => $audit['applicantId'],
                        "type"   => $audit['flowName'],
                        "typeId" => $audit['id'],
                        "text"   => str_replace(['{{flowName}}'], [$audit['flowName']], L('audit.table.pass')),
                    ));
                }
                //添加审批记录
                auditingFollow([
                    "type"      => $audit['flowName'],
                    "typeId"    => $audit['id'],
                    "text"      => "【{$this->control['name']}】转交了【{$audit['flowName']}】",
                    'remark'    => '',
                    'staffName' => $this->control['name'],
                    'job'       => self::findStaffDepartment(self::$stid) . '-' . $this->controlJob['name'],
                ]);
                //更新审批表
                $field = [
                    'approver'   => implode(',', $result['staffName']),
                    'workFlow'   => $result['isEnd'] ? '已通过' : '审核中',
                    'approverId' => implode(',', $result['staffId']),
                ];
                if ($result['nodeIsEnd']) {
                    $field['commitTimePrevious'] = $this->time;//更新上节点提交时间
                }

                $warn = update(array('table' => 'audit', 'field' => $field, 'where' => "id = '$audit[id]'"));
                if ($warn == '更新成功') {
                    //待办提醒
                    self::sendTip($result['staffId'], $audit['id'], str_replace(['{{deptName}}', '{{staffName}}', '{{name}}'], [$audit['applicantDepartment'], $audit['applicant'], $audit['flowName']], L('audit.table.commitAudit')));
//                    self::findAutoNode($result['flow'],$audit['flowName'],$audit['id'],"【{$audit['applicantDepartment']}】-【{$audit['applicant']}】提交的【{$audit['flowName']}】需要您审批");
                }
                //更新待办
                backlogEnd(array(
                    "stid"   => $this->control['stid'],
                    "typeId" => $audit['id'],
                ));

                $json['warn']     = 2;
                $_SESSION['warn'] = L('audit.table.zjcg');
            } else {
                $json['warn'] = L('audit.table.zjsb');
            }
        }
        return json_encode($json, 320);
    }

    /**
     * 找到需要发送待办的自动审批节点，写入已处理待办
     */
    public static function findAutoNode($flow, $flowName, $auditId, $text)
    {
        $staffs = [];//需要增加已处理待办的员工ID数组
        foreach ($flow as $array) {
            $array['isAuto'] = $array['isAuto'] ?? '否';
            if ($array['form'] == 'approver') {
                if ($array['state'] == '审核中') {
                    //遇到目前审核中状态的节点，则退出
                    break;
                }
                if ($array['isAuto'] == '是') {
                    $auditStaff = explode(';', $array['staff[]']);//当前节点的审核人数组
                    $auditStaff = array_filter($auditStaff);
                    if ($array['multiType'] == '或签') {
                        $auditStaff = isset($auditStaff[0]) ? [$auditStaff[0]] : [];
                    }
                    $staffs = $auditStaff;
                } else {
                    //遇到非自动审批节点，则清空已发送了待办的员工数组ID
                    $staffs = [];
                }
            }
        }
        self::generateDoneTip($staffs, $flowName, $auditId, $text);
    }

    /**
     * 发送待办
     */
    public static function sendTip(array $staffId, string $auditId, string $text)
    {
        $info = query('audit', " id = '$auditId'");
        foreach ($staffId as $stid) {
            $backlog = query('backlog', "typeId = '$auditId' and stid = '$stid' and workFlow = '待处理'");
            $staff   = query('staff', "stid = '$stid'");
            if (empty($backlog['id']) && $staff['state'] != '离职') {
                $id = self::getId();
                backlogIn([
                    'id'     => $id,
                    "coid"   => self::$coid,
                    "stid"   => $stid,
                    "type"   => $info['flowName'],
                    "typeId" => $auditId,
                    "text"   => $text,
                ]);
                //发送小程序消息
                $content     = [
                    [
                        'key'   => '审批类型',
                        'value' => $info['flowName'],
                    ],
                    [
                        'key'   => '内容',
                        'value' => $text,
                    ],
                ];
                $description = '发起时间：' . date('m-d H:i', strtotime($info['commitTime']));
                self::sendMiniProgramMessage([$stid], $content, $info['targetId'], $info['flowName'], $id, $description);
            }
        }
    }

    /**
     * 批量发送消息
     *
     * @param array $staffId
     * @param string $auditId
     * @param string $text
     */
    public static function batchMessage(array $staffId, string $auditId, string $text)
    {
        $info = query('audit', " id = '$auditId'");
        foreach ($staffId as $stid) {
            $staff = query('staff', "stid = '$stid'");
            if ($staff['state'] != '离职') {
                message([
                    "stid"   => $stid,
                    "type"   => $info['flowName'],
                    "typeId" => $auditId,
                    "text"   => $text,
                ]);
            }
        }
    }

    /**
     * 寻找审批顺序
     */
    public function findAuditOrder($flow): array
    {
        $staffNode = 0;//当前审批节点第几次审批
        $auditNode = 0;//处于第几个审批节点
        foreach ($flow as $array) {
            if ($array['form'] == 'approver') {
                $auditNode++;
                if ($array['state'] == '审核中') {
                    if ($array['multiType'] == '或签') {
                        $staffNode++;
                    } elseif ($array['multiType'] == '依次审批') {
                        foreach ($array['stateNode'] as $item) {
                            $staffNode++;
                            if ($item['state'] == '审核中') {
                                break;
                            }
                        }
                    } elseif ($array['multiType'] == '会签') {
                        foreach ($array['stateNode'] as $item) {
                            if ($item['state'] == '审核中') {
                                $staffNode++;
                            }
                        }
                    }
                    break;
                }
            }
        }
        return ['auditNode' => $auditNode, 'staffNode' => $staffNode];
    }


    /**
     * 撤销发送的企业微信消息
     *
     * @param $auditId
     */
    public static function revokeMessage($auditId)
    {
        $all = find(array('table' => 'backlog', 'where' => "typeId='$auditId' and workFlow = '待处理'"));
        foreach ($all['array'] as $array) {
            $message = query('message_we_chat', "messageId = '$array[id]'");
            if (!empty($message['id'])) {
                self::revokeQyMessage($message['qyMessageId']);
            }
        }
    }

    /**
     * @param array $stids 员工数组
     * @param array $content 内容  array(['key'=>'','value'=>''])
     * @param string $targetId 对象ID
     * @param string $target 类型
     * @param string $messageId 关联的待办ID
     */
    public static function sendMiniProgramMessage(array $stids, $content, $targetId, $target, $messageId, $description = '')
    {
        $whileField = [
            '付款申请'     => '/pages/paymentInfo/paymentInfo?id=' . $targetId,
            '费用报销'     => '/pages/costInfo/costInfo?id=' . $targetId,
            '费用申请'     => '/pages/feeApplyInfo/feeApplyInfo?id=' . $targetId,
            '外出申请'     => '/pages/workOutInfo/workOutInfo?id=' . $targetId,
            '外出成果审核' => '/pages/workOutInfo/workOutInfo?id=' . $targetId,
            '出差申请'     => '/pages/bussinessTripDetail/bussinessTripDetail?id=' . $targetId,
            '出差成果审核' => '/pages/bussinessTripDetail/bussinessTripDetail?id=' . $targetId,
            '加班申请'     => '/pages/workInfo/workInfo?id=' . $targetId,
            '加班成果审核' => '/pages/workInfo/workInfo?id=' . $targetId,
            '补卡申请'     => '/pages/workSignAddInfo/workSignAdInfo?id=' . $targetId,
            '请假申请'     => '/pages/workHolidayInfo/workHolidayInfo?id=' . $targetId,
        ];
        if (in_array($target, array_keys($whileField))) {
            $user_sertting = query('user_setting', "stid = '" . self::$stid . "' and type = 'OA通知设置'");
            $setting       = json_decode($user_sertting['value'], true);
            if ($setting['message']) {
                //设置打开，则发送消息
                $result = self::sendQYWechatMessage($stids, L('audit.table.dsptx'), $content, $whileField[$target], $description);
                if ($result !== false) {
                    $msgId = $result['msgid'];
                    foreach ($stids as $stid) {
                        $staff = query('staff', "stid = '$stid'");
                        if ($staff != '离职') {
                            static::insert(array(
                                'table' => 'message_we_chat',
                                'field' => [
                                    'stid'        => $stid,
                                    'targetId'    => $targetId,
                                    'target'      => $target,
                                    'messageId'   => $messageId,
                                    'qyMessageId' => $msgId,
                                ],
                            ));
                        }
                    }
                }
            }
        }
    }

}
